package com.zmn.plat.business.impl.price.meter3;

import com.alibaba.fastjson.JSONArray;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto.KvDTO;
import com.zmn.common.dto.VtDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.plat.business.interfaces.base.acceptproject.AcceptProjectBService;
import com.zmn.plat.business.interfaces.channel.ChannelServiceCategoryBService;
import com.zmn.plat.business.interfaces.price.meter3.MeterFlow3BService;
import com.zmn.plat.business.interfaces.price.meter3.MeterFlow3CommonBService;
import com.zmn.plat.business.interfaces.product.ServProductBService;
import com.zmn.plat.common.constant.ItemCategoryConsts;
import com.zmn.plat.common.dictionary.BaseAcceptProjectTypeEnum;
import com.zmn.plat.common.dictionary.BaseBrandRatioTypeEnum;
import com.zmn.plat.common.dictionary.PlatErrorCodeDict;
import com.zmn.plat.common.dto.base.AcceptProjectDRO;
import com.zmn.plat.common.dto.base.FaultDRO;
import com.zmn.plat.common.dto.base.PhenomenonDRO;
import com.zmn.plat.common.dto.base.ServiceContentDRO;
import com.zmn.plat.common.dto.brand.BaseBrandDRO;
import com.zmn.plat.common.dto.price.meter3.*;
import com.zmn.plat.common.dto.product.tariff.TariffBackProductDRO;
import com.zmn.plat.common.exception.PlatException;
import com.zmn.plat.common.util.StringToArrayUtil;
import com.zmn.plat.manager.dictionary.ProductDict;
import com.zmn.plat.model.dto.product.ProductRelationDTO;
import com.zmn.plat.model.entity.base.acceptproject.AcceptProject;
import com.zmn.plat.model.entity.base.fault.FaultQuery;
import com.zmn.plat.model.entity.base.phenomenon.PhenomenonFault;
import com.zmn.plat.model.entity.base.phenomenon.PhenomenonFaultQuery;
import com.zmn.plat.model.entity.brand.BaseBrand;
import com.zmn.plat.model.entity.brand.BaseBrandQuery;
import com.zmn.plat.model.entity.brand.BrandRatio;
import com.zmn.plat.model.entity.product.ServProduct;
import com.zmn.plat.model.entity.product.categorybrand.CategoryBrandQuery;
import com.zmn.plat.model.entity.product.tariff.item.ProductItemQuery;
import com.zmn.plat.model.entity.product.tariff.item.ProductTariffGroupItemQuery;
import com.zmn.plat.model.entity.servcategory.ServAssCategoryQuery;
import com.zmn.plat.model.vo.servcategory.ServAssCategoryVO;
import com.zmn.plat.services.interfaces.base.acceptproject.AcceptProjectService;
import com.zmn.plat.services.interfaces.base.fault.FaultService;
import com.zmn.plat.services.interfaces.base.phenomenon.PhenomenonFaultService;
import com.zmn.plat.services.interfaces.base.phenomenon.PhenomenonService;
import com.zmn.plat.services.interfaces.base.servicecontent.ServiceContentService;
import com.zmn.plat.services.interfaces.brand.BaseBrandService;
import com.zmn.plat.services.interfaces.brand.BrandRatioService;
import com.zmn.plat.services.interfaces.channel.brand.ratio.ChannelBrandRatioService;
import com.zmn.plat.services.interfaces.product.ServProductService;
import com.zmn.plat.services.interfaces.product.categorybrand.CategoryBrandService;
import com.zmn.plat.services.interfaces.product.tariff.tariffproductitem3.TariffProductItem3Service;
import com.zmn.plat.services.interfaces.servcategory.ServAssCategoryService;
import com.zmn.plat.utils.bean.BeanCopyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述: 计价器3.0流程实现类
 *
 * @author guoqiao
 * @since 2021/11/24 18:58
 */
@Slf4j
@Service
public class MeterFlow3BServiceImpl implements MeterFlow3BService {

    @Resource
    ServProductService servProductService;
    @Resource
    ServProductBService servProductBService;
    @Resource
    MeterFlow3CommonBService meterFlow3CommonBService;
    @Resource
    CategoryBrandService categoryBrandService;
    @Resource
    ChannelServiceCategoryBService channelServiceCategoryBService;
    @Resource
    ChannelBrandRatioService channelBrandRatioService;
    @Resource
    BrandRatioService brandRatioService;
    @Resource
    BaseBrandService baseBrandService;
    @Resource
    TariffProductItem3Service tariffProductItem3Service;
    @Resource
    ServAssCategoryService servAssCategoryService;
    @Resource
    ServiceContentService serviceContentService;
    @Resource
    AcceptProjectBService acceptProjectBService;
    @Resource
    AcceptProjectService acceptProjectService;
    @Resource
    FaultService faultService;
    @Resource
    PhenomenonFaultService phenomenonFaultService;
    @Resource
    private PhenomenonService phenomenonService;

    @Override
    @Cacheable(cacheNames = "redis10m", key = "'price3:listErpProductByQuery:MeterErpProductQuery3:'+#p0", unless = "#result == null")
    public List<TariffBackProductDRO> listErpProductByQuery(MeterErpProductQuery3 query) {

        Integer productId = query.getProductId();
        Integer channelId = query.getChannelId();
        Integer bizType = query.getBizType();
        Integer tariffId = query.getTariffId();

        // 查询前台、后台、计价器产品关系
        List<ProductRelationDTO> relationDTOS = servProductBService.listProductRalationByIdListAndShowType(Arrays.asList(productId), ProductDict.EC_PRODUCT_TYPE);
        if (CollectionUtils.isEmpty(relationDTOS)) {
            return Collections.emptyList();
        }
        List<TariffBackProductDRO> dros = new ArrayList<>(relationDTOS.size());
        for (ProductRelationDTO relationDTO : relationDTOS) {
            Boolean flag = false;
            if (NumberUtil.isNullOrZero(tariffId)) {
                // 查询计价器3.0价格表
                ProductTariffTypeDRO productTariffType = meterFlow3CommonBService.getProductTariffType(channelId, relationDTO.getProductId(), bizType, ProductDict.TRIFF_TYPE_TARIFF3);
                flag = Objects.nonNull(productTariffType);
            } else {
                // 自带价格表id
                ProductTariffGroupItemQuery itemQuery = new ProductTariffGroupItemQuery();
                itemQuery.setProductId(relationDTO.getProductId());
                itemQuery.setTariffId(tariffId);
                itemQuery.setCategId(ItemCategoryConsts.MAINTAIN_ITEM);
                int count = tariffProductItem3Service.countByQuery(itemQuery);
                flag = count > 0;
            }

            if (flag) {
                // 查询产品
                ServProduct servProduct = servProductService.findByKeyWithCache(relationDTO.getProductId());
                TariffBackProductDRO dro = new TariffBackProductDRO();
                BeanCopyUtils.copyProperties(servProduct, dro);
                dro.setProductName(servProduct.getName());
                dro.setProductTariffName(servProduct.getTariffName());
                dro.setProductSort(servProduct.getSort());
                dros.add(dro);
            }
        }
        return dros;
    }

    @Override
    @Cacheable(cacheNames = "redis10m", key = "'price3:listBrandByQuery:MeterBaseQuery3:'+#p0", unless = "#result == null")
    public List<BaseBrandDRO> listBrandByQuery(MeterBaseQuery3 query) {

        // 查询前台、后台、计价器产品关系
        List<ProductRelationDTO> relationDTOS = servProductBService.listProductRalationByIdListAndShowType(Arrays.asList(query.getProductId()), ProductDict.ERP_PRODUCT_TYPE);
        if (CollectionUtils.isEmpty(relationDTOS)) {
            return Collections.emptyList();
        }
        ProductRelationDTO relationDTO1 = relationDTOS.get(0);

        // 查询前台分类关联了的品牌
        CategoryBrandQuery categoryBrandQuery = new CategoryBrandQuery();
        categoryBrandQuery.setCategId(relationDTO1.getShowCategId());
        categoryBrandQuery.setStatus(GlobalConsts.YES);
        List<Integer> categBrandIdList = Optional.ofNullable(categoryBrandService.listByQuery(categoryBrandQuery))
                .orElse(Collections.emptyList())
                .stream()
                .map(e -> e.getBrandId())
                .collect(Collectors.toList());

        // 查询基础数据的品牌系数
        List<BrandRatio> brandRatios = brandRatioService.listForFlowByBizType(4);
        log.info("品牌系数brandRatios：{}", brandRatios);
        if (CollectionUtils.isEmpty(brandRatios)) {
            return Collections.emptyList();
        }

        List<Integer> brandIdList = new ArrayList<>(brandRatios.size());

        Set<String> categOneStrs = new HashSet<>(relationDTOS.size()); // 后台产品一级分类系数str
        Set<String> categTwoStrs = new HashSet<>(relationDTOS.size()); // 后台产品二级分类系数str
        for (ProductRelationDTO relationDTO : relationDTOS) {
            categOneStrs.add(relationDTO.getServCategId() + "-" + relationDTO.getCategOneId());
            categTwoStrs.add(relationDTO.getServCategId() + "-" + relationDTO.getCategOneId() + "-" + relationDTO.getCategId());
        }

        for (BrandRatio brandRatio : brandRatios) {
            Integer brandId = brandRatio.getBrandId();
            Integer ratioType = brandRatio.getRatioType();
            if (brandIdList.contains(brandId) || !categBrandIdList.contains(brandId)) {
                continue;
            }
            if (Objects.equals(BaseBrandRatioTypeEnum.BRANDCATEGONERATIO.getCode(), ratioType)
                    && categOneStrs.contains(brandRatio.getServCategId() + "-" + brandRatio.getCategOneId())) {
                // 后台产品一级分类系数
                brandIdList.add(brandId);
            } else if (Objects.equals(BaseBrandRatioTypeEnum.BRANDCATEGTWORATIO.getCode(), ratioType)
                    && categTwoStrs.contains(brandRatio.getServCategId() + "-" + brandRatio.getCategOneId() + "-" + brandRatio.getCategId())) {
                // 后台产品二级分类系数
                brandIdList.add(brandId);
            }
        }
        log.info("符合条件的品牌id集合brandIdList：{}", brandIdList);
        if (CollectionUtils.isEmpty(brandIdList)) {
            return Collections.emptyList();
        }

        // 查询品牌信息
        BaseBrandQuery brandQuery = new BaseBrandQuery();
        brandQuery.setBrandIdList(brandIdList);
        brandQuery.setStatus(GlobalConsts.YES);
        List<BaseBrand> baseBrands = baseBrandService.listByQuery(brandQuery);
        List<BaseBrandDRO> baseBrandDROS = BeanCopyUtils.copyProperties(baseBrands, BaseBrand.class, BaseBrandDRO.class, BaseBrandDRO::new);
        return baseBrandDROS;
    }

    @Override
    @Cacheable(cacheNames = "redis10m", key = "'price3:listPhenoByQuery:MeterBaseQuery3:'+#p0", unless = "#result == null")
    public List<PhenomenonDRO> listPhenoByQuery(MeterBaseQuery3 query) {

        // 查询item集合
        List<ItemDRO3> itemList = this.listItemDRO(query);
        if (CollectionUtils.isEmpty(itemList)) {
            return Collections.emptyList();
        }
        // 项目关联的故障id集合
        List<Integer> faultIdList = new ArrayList<>();
        for (ItemDRO3 item : itemList) {
            if (Objects.nonNull(item.getFaultList())) {
                List<Integer> faultIds = StringUtil.split(item.getFaultList(), Integer.class);
                faultIdList.addAll(faultIds);
            }
        }

        // 根据故障id 查询故障现象(具体故障关联)
        PhenomenonFaultQuery phenomenonFaultQuery = PhenomenonFaultQuery.builder().faultIds(faultIdList).build();
        List<Integer> phenIds = Optional.ofNullable(phenomenonFaultService.listByQuery(phenomenonFaultQuery))
                .orElse(Collections.emptyList())
                .stream()
                .map(e -> e.getPhenId())
                .distinct()
                .collect(Collectors.toList());

        if (CollectionUtil.isNullOrEmpty(phenIds)) {
            return Collections.emptyList();
        }

        // 产品基本信息
        ServProduct product = servProductService.findByKeyWithCache(query.getProductId());
        if (Objects.isNull(product)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_PRODUCT_NULL);
        }
        // 产品二级分类关联的故障现象id
        List<Integer> phenIdList = new ArrayList<>();
        List<ServAssCategoryVO> servAssCategories = servAssCategoryService.listByQuery(ServAssCategoryQuery.builder()
                .servCategId(product.getServCategId())
                .categId(product.getCategId()).build());
        if (!CollectionUtils.isEmpty(servAssCategories)) {
            ServAssCategoryVO servAssCategoryVO = servAssCategories.get(0);
            String phenoIdStr = servAssCategoryVO.getFault();
            if (Objects.nonNull(phenoIdStr)) {
                phenIdList = StringToArrayUtil.convertStrsToList(phenoIdStr);
            }
        }

        phenIds.retainAll(phenIdList); // 交集
        if (CollectionUtil.isNullOrEmpty(phenIds)) {
            return Collections.emptyList();
        }

        // 查询全部有效故障现象详情
        List<PhenomenonDRO> phenomenonDroList = Optional.ofNullable(phenomenonService.listByIds(phenIds))
                .orElse(Collections.emptyList())
                .stream()
                .filter(e -> Objects.equals(GlobalConsts.YES, e.getStatus()))
                .map(e -> {
                    PhenomenonDRO dro = new PhenomenonDRO();
                    BeanCopyUtils.copyProperties(e, dro);
                    return dro;
                })
                .collect(Collectors.toList());
        return phenomenonDroList;
    }

    @Override
    @Cacheable(cacheNames = "redis10m", key = "'price3:listFaultByQuery:MeterFaultQuery3:'+#p0", unless = "#result == null")
    public List<FaultDRO> listFaultByQuery(MeterFaultQuery3 query) {

        MeterBaseQuery3 baseQuery3 = new MeterBaseQuery3();
        BeanCopyUtils.copyProperties(query, baseQuery3);
        // 查询item集合
        List<ItemDRO3> itemList = this.listItemDRO(baseQuery3);
        if (CollectionUtils.isEmpty(itemList)) {
            return Collections.emptyList();
        }
        // 项目关联的故障id集合
        List<Integer> itemFaultIdList = new ArrayList<>();
        for (ItemDRO3 item : itemList) {
            if (Objects.nonNull(item.getFaultList())) {
                List<Integer> faultIds = StringUtil.split(item.getFaultList(), Integer.class);
                itemFaultIdList.addAll(faultIds);
            }
        }

        // 根据故障现象id 查询故障现象-具体故障关联->获取故障id
        PhenomenonFaultQuery phenomenonFaultQuery = PhenomenonFaultQuery.builder().phenIds(query.getPhenIdList()).build();
        List<Integer> faultIds = Optional.ofNullable(phenomenonFaultService.listByQuery(phenomenonFaultQuery))
                .orElse(Collections.emptyList())
                .stream()
                .map(PhenomenonFault::getFaultId)
                .distinct()
                .filter(e -> itemFaultIdList.contains(e))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(faultIds)) {
            return Collections.emptyList();
        }

        // 查询全部具体故障详情
        List<FaultDRO> droList = Optional.ofNullable(faultService.listByQuery(FaultQuery.builder()
                        .faultIds(faultIds)
                        .status(GlobalConsts.YES)
                        .build())
                )
                .orElse(Collections.emptyList())
                .stream()
                .filter(e -> Objects.equals(GlobalConsts.YES, e.getStatus()))
                .map(e -> {
                    FaultDRO dro = new FaultDRO();
                    BeanCopyUtils.copyProperties(e, dro);
                    return dro;
                }).collect(Collectors.toList());
        return droList;
    }

    @Override
    @Cacheable(cacheNames = "redis10m", key = "'price3:listServiceContentByQuery:MeterContentQuery3:'+#p0", unless = "#result == null")
    public List<ServiceContentDRO> listServiceContentByQuery(MeterContentQuery3 query) {

        MeterBaseQuery3 baseQuery = new MeterBaseQuery3();
        BeanCopyUtils.copyProperties(query, baseQuery);
        // 查询item集合
        List<ItemDRO3> itemList = this.listItemDRO(baseQuery);
        if (CollectionUtils.isEmpty(itemList)) {
            return Collections.emptyList();
        }
        // 项目关联的服务内容id集合
        List<Integer> serviceContentIdList = new ArrayList<>();
        for (ItemDRO3 item : itemList) {
            if (Objects.nonNull(item.getServiceContentList()) && query.getItemList().contains(item.getItemId())) {
                List<Integer> serviceContentIds = StringUtil.split(item.getServiceContentList(), Integer.class);
                serviceContentIdList.addAll(serviceContentIds);
            }
        }

        // 产品基本信息
        ServProduct product = servProductService.findByKeyWithCache(query.getProductId());
        if (Objects.isNull(product)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_PRODUCT_NULL);
        }
        // 产品二级分类关联的服务内容
        List<ServAssCategoryVO> servAssCategories = servAssCategoryService.listByQuery(ServAssCategoryQuery.builder()
                .servCategId(product.getServCategId())
                .categId(product.getCategId()).build());
        if (!CollectionUtils.isEmpty(servAssCategories)) {
            ServAssCategoryVO servAssCategoryVO = servAssCategories.get(0);
            String serviceContent = servAssCategoryVO.getServiceContent();
            if (Objects.nonNull(serviceContent)) {
                List<Integer> serviceContentIds = StringToArrayUtil.convertStrsToList(serviceContent);
                serviceContentIdList.addAll(serviceContentIds);
            }
        }
        if (CollectionUtils.isEmpty(serviceContentIdList)) {
            return Collections.emptyList();
        }

        // 查询服务内容 过滤停用状态服务内容
        List<ServiceContentDRO> droList = Optional.ofNullable(serviceContentService.listByIds(serviceContentIdList))
                .orElse(Collections.emptyList())
                .stream()
                .filter(e -> Objects.equals(GlobalConsts.YES, e.getStatus()))
                .map(e -> {
                    ServiceContentDRO dro = new ServiceContentDRO();
                    BeanCopyUtils.copyProperties(e, dro);
                    return dro;
                }).collect(Collectors.toList());
        return droList;
    }

    @Override
    @Cacheable(cacheNames = "redis10m", key = "'price3:listAcceptItemByQuery:MeterAcceptQuery3:'+#p0", unless = "#result == null")
    public List<AcceptProjectDRO> listAcceptItemByQuery(MeterAcceptQuery3 query) {

        List<AcceptProjectDRO> droList = new ArrayList<>();
        // 产品基本信息
        ServProduct product = servProductService.findByKeyWithCache(query.getProductId());
        if (Objects.isNull(product)) {
            throw new PlatException(PlatErrorCodeDict.ERROR_CODE_SERVICE_PRODUCT_NULL);
        }
        // 二级分类关联的验收项目（用户端和工程师端都会用到）
        List<AcceptProject> acceptProjects = acceptProjectBService.listEfficientAcceptProjectByServCategIdAndCategId(product.getServCategId(), product.getCategId(), query.getAcceType());
        for (AcceptProject acceptProject : acceptProjects) {
            AcceptProjectDRO dro = new AcceptProjectDRO();
            BeanCopyUtils.copyProperties(acceptProject, dro);
            // 1故障检测
            dro.setType(GlobalConsts.NO);
            String selectValue = acceptProject.getSelectValue();
            if (StringUtil.isNotBlank(selectValue)) {
                List<VtDTO> vts = JSONArray.parseArray(selectValue, VtDTO.class);
                dro.setSelectValue(vts);
            }
            droList.add(dro);
        }

        // 工程师验收项目
        if (Objects.equals(BaseAcceptProjectTypeEnum.ENGINEER_ACCEPT.getCode(), query.getAcceType())) {
            List<Integer> itemIdList = query.getItemIdList();
            if (CollectionUtils.isEmpty(itemIdList)) {
                throw new PlatException("服务项id必传");
            }
            MeterBaseQuery3 baseQuery3 = new MeterBaseQuery3();
            BeanCopyUtils.copyProperties(query, baseQuery3);
            // 查询item集合
            List<ItemDRO3> itemList = Optional.ofNullable(this.listItemDRO(baseQuery3))
                    .orElse(Collections.emptyList())
                    .stream()
                    .filter(e -> itemIdList.contains(e.getItemId()))
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(itemList)) {
                // 项目关联的验收项目id集合
                List<Integer> acceptProjectIdList = new ArrayList<>();
                for (ItemDRO3 item : itemList) {
                    if (Objects.nonNull(item.getAcceptProjectList())) {
                        List<Integer> acceptProjectIds = StringUtil.split(item.getAcceptProjectList(), Integer.class);
                        acceptProjectIdList.addAll(acceptProjectIds);
                    }
                }
                if (!CollectionUtils.isEmpty(acceptProjectIdList)) {
                    // 查询验收项目 过滤停用状态服务内容
                    List<AcceptProjectDRO> projectList = Optional.ofNullable(acceptProjectService.listByIds(acceptProjectIdList))
                            .orElse(Collections.emptyList())
                            .stream()
                            .filter(e -> Objects.equals(GlobalConsts.YES, e.getStatus()))
                            .map(e -> {
                                AcceptProjectDRO dro = new AcceptProjectDRO();
                                BeanCopyUtils.copyProperties(e, dro);
                                dro.setType(GlobalConsts.YES); // 2故障点检测
                                String selectValue = e.getSelectValue();
                                if (StringUtil.isNotBlank(selectValue)) {
                                    List<VtDTO> vts = JSONArray.parseArray(selectValue, VtDTO.class);
                                    dro.setSelectValue(vts);
                                }
                                return dro;
                            }).collect(Collectors.toList());
                    droList.addAll(projectList);
                }
            }
        }
        return droList;
    }

    private List<ItemDRO3> listItemDRO(MeterBaseQuery3 query) {
        Integer tariffId = query.getTariffId();
        if (NumberUtil.isNullOrZero(tariffId)) {
            // 查询计价器3.0价格表
            ProductTariffTypeDRO productTariffType = meterFlow3CommonBService.getProductTariffType(query.getChannelId(), query.getProductId(), query.getBizType(), ProductDict.TRIFF_TYPE_TARIFF3);
            if (Objects.isNull(productTariffType)) {
                return Collections.emptyList();
            }
            tariffId = productTariffType.getTariffId();
        }
        // 查询item集合
        ProductItemQuery itemQuery = new ProductItemQuery();
        itemQuery.setKvList(Arrays.asList(new KvDTO(query.getProductId(), tariffId)));
        itemQuery.setItemCategId(ItemCategoryConsts.MAINTAIN_ITEM);
        List<ItemDRO3> itemList = tariffProductItem3Service.listItemPriceByQuery(itemQuery);
        return itemList;
    }
}
